<!--
=========================================================
* Argon Dashboard - v1.2.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard


* Copyright  Creative Tim (http://www.creative-tim.com)
* Coded by www.creative-tim.com



=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head th:replace="fragments/common :: head_and_imports"></head>

<body>
<!-- Sidenav -->
<nav th:replace="fragments/common :: sidnav(1)"></nav>

<!-- Main content -->
<div class="main-content" id="panel">
	<!-- Topnav -->
	<nav class="navbar navbar-top navbar-expand navbar-dark bg-primary border-bottom d-md-none">
		<div class="container-fluid">
			<div class="collapse navbar-collapse row justify-content-between" id="navbarSupportedContent">
				<div class="row col-auto justify-content-end align-items-center m-0">
					<div class="col-auto">
						<ul class="navbar-nav align-items-center">
							<li class="nav-item d-xl-none">
								<!-- Sidenav toggler -->
								<div class="pr-2 sidenav-toggler sidenav-toggler-dark" data-action="sidenav-pin"
								     data-target="#sidenav-main">
									<div class="sidenav-toggler-inner">
										<i class="sidenav-toggler-line"></i>
										<i class="sidenav-toggler-line"></i>
										<i class="sidenav-toggler-line"></i>
									</div>
								</div>
							</li>
						</ul>
					</div>
				</div>
			</div>
		</div>
	</nav>
	
	<!-- Header -->
	<div class="header bg-primary">
		<div class="container-fluid">
			<!-- Header container -->
			<div class="container-fluid d-flex align-items-center">
				<div class="row">
					<div class="col-lg-10 col-md-10 mt-5 mb-8">
						<h1 class="display-2 text-white">Lines of Code or Comments</h1>
						<p class="text-white text-justify mb-3">
							These metrics calculate the lines of you project. Currently, T4M only count the number of
							lines of java source code. T4M provides two statistical methods for counting the LOC, including
							<code>Per Class</code> that is based on the source files
							and <code>Per File</code> that is based on declared classes.
						</p>
						<p class="text-white text-justify mb-3">
							For the methods based on the source file, the java file will be the minimum unit that T4M analysis.
							Each line will be counted without any formatting.
						</p>
						<div class="collapse" id="collapse_description">
							<p class="text-white text-justify mb-3">
								For the method based on declared class, the minimum unit that T4M analysis is classes rather than
								java files. Recall that a java file can declare one public outer class, multiple package-private
								classes and multiple nested classes. The class will be formatted by
								<a class="text-yellow text-link" href="http://javaparser.org/">JavaParser</a> before being
								analysed, which split the code statement and the comment into different lines. Besides, the import
								and package statement will be excluded.
							</p>
							<p class="text-white text-justify mb-3">
								There are three metrics here, Source Lines of Code, Number of Comment Lines and Percentage of
								Comment Lines. Notice that the empty lines are excluded.
							</p>
							<p class="text-white text-justify mb-3">
								Detailed definitions and influences of LOC/SLOC:
								<a class="text-yellow text-link"
								   href="https://maisqual.squoring.com/wiki/index.php/Source_Lines_of_Code">
									Maisqual - Source Lines of Code</a>,
								<a class="text-yellow text-link" href="http://www.arisa.se/compendium/node91.html">
									ARiSA - Lines of Code</a>,
								<a class="text-yellow text-link" href="https://en.wikipedia.org/wiki/Source_lines_of_code">
									Wiki - Source lines of code</a>.
							</p>
						</div>
						<a class="text-white text-link" data-toggle="collapse" href="#collapse_description"
						   role="button" aria-expanded="false" aria-controls="collapse_description">
							<i class="fas fa-sort"></i> Expand / Collapse
						</a>
					</div>
				</div>
			</div>
		</div>
	</div>
	
	<!-- Page content -->
	<div class="container-fluid mt--6" th:with="currentProjectInfo = ${projectList.get(projectList.size()-1)}">
		<div class="row">
			<!-- chart -->
			<div class="col-xl-12">
				<div class="card">
					<div class="card-header bg-transparent">
						<div class="row align-items-center">
							<div class="col">
								<h6 class="text-muted text-uppercase ls-1 mb-1">Overview</h6>
								<h5 class="h3 mb-0">
									The distribution of classes on the Source Lines of Code and Number of Comment Lines,
									and its evolution during developing.
								</h5>
							</div>
							<div class="col">
								<ul class="nav nav-pills justify-content-end">
									<li class="nav-item mr-2 mr-md-0">
										<a href="javascript:void(0);" class="nav-link py-2 px-3"
										   data-toggle="tab"
										   onclick="changeDataSet('allClass')">
											<span class="d-none d-md-block">Per Class (JavaParser Format)</span>
											<span class="d-md-none">C</span>
										</a>
									</li>
									<li class="nav-item">
										<a id='sloc_timeline_chart' href="javascript:void(0);" class="nav-link py-2 px-3 active"
										   data-toggle="tab" onclick="changeDataSet('file')">
											<span class="d-none d-md-block">Per File (Original format)</span>
											<span class="d-md-none">F</span>
										</a>
									</li>
								</ul>
							</div>
						</div>
					</div>
					
					<div id="chart" class="card-body pb-4 pr-4 pl-0 pt-0 col-12" style="height:650px;"></div>
					<div class="modal fade" id="chart_data_model" tabindex="-1" role="dialog"
					     aria-labelledby="row_model_label" aria-hidden="true">
						<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
							<div class="modal-content">
								<div class="modal-header">
									<h5 class="modal-title">{{title}}</h5>
									<button type="button" class="close" data-dismiss="modal" aria-label="Close">
										<span aria-hidden="true">&times;</span>
									</button>
								</div>
								<div class="modal-body pt-0">
									<hr class="my-3">
									<div v-for="pointValue in pointValueList">
										<span>{{pointValue}}</span><br>
									</div>
									<hr class="my-3">
									<div v-for="pointDescription in pointDescriptionList">
										<div v-html="pointDescription"></div>
										<hr class="my-1">
									</div>
								</div>
								<div class="modal-footer">
									<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
								</div>
							</div>
						</div>
					</div>
					
					<script type="text/javascript" th:inline="javascript">
              let timeRecords = /*[[${timeRecords}]]*/;
              let datasetAllClass = /*[[${datasetAllClass}]]*/;
              let datasetMainClass = /*[[${datasetMainClass}]]*/;
              let datasetKeyArray = ['Interface', 'Abstract Class', 'Class', 'Enum', 'Annotation', 'info.java']
              let currentDataset;

              let chartLevel = "file";

              function changeDataSet(type) {
                  chartLevel = type;
                  let label;
                  if (type === 'allClass') {
                      currentDataset = datasetAllClass;
                      label = ['Class', '', 'Number of source lines of code',
                          'Number of comment lines', '% of comment lines']
                  } else if (type === 'file') {
                      currentDataset = datasetMainClass;
                      label = ['Source File', '.java',
                          'Number of source lines of code',
                          'Number of comment lines', '% of comment lines']
                  }
                  let dataMax = getMax(currentDataset);
                  let options = optionsFormatter(currentDataset);
                  let option = {
                      options: options,
                      baseOption: {
                          grid: {bottom: 100, right: 150}, color: ['#c23531'],
                          legend: {
                              data: ['Class', 'Enum', 'Annotation', 'Interface', 'Abstract Class',
                                  'package/module-info'],
                              selected: {'package/module-info': false},
                          },
                          xAxis: {
                              name: 'Source Lines of Code', type: 'value', max: Math.ceil(dataMax[0] / 5) * 5,
                              nameLocation: 'center', nameGap: 28
                          },
                          yAxis: {
                              name: 'Number of Comment Lines', type: 'value', max: Math.ceil(dataMax[1] / 5) * 5,
                              nameLocation: 'center', nameRotate: 90, nameGap: 30
                          },
                          timeline: {
                              axisType: 'category', loop: true, autoPlay: false, currentIndex: timeRecords.length - 1,
                              playInterval: 1000, symbol: 'circle', data: timeRecords,
                              controlStyle: {showNextBtn: true, showPrevBtn: true, showPlayBtn: true},
                              checkpointStyle: {animation: false},
                              label: {
                                  formatter: function (value, index) {
                                      return value.split(" ")[0];
                                  }
                              }
                          },
                          tooltip: {
                              padding: 10, borderWidth: 1,
                              show: true, enterable: true, trigger: 'item', confine: true,
                              formatter: function (params) {
                                  if (params.componentType === "timeline") {
                                      return params.name;
                                  } else {
                                      let value = params.data
                                      return '<div style="border-bottom: 1px solid rgba(255,255,255,.3) ;padding-bottom: 7px;margin-bottom: 7px">'
                                          + label[0] + ': ' + value[3] + label[1] + '<br>'
                                          + '<span style="font: 12px">'
                                          + 'Of Module: ' + value[4] + '</span>' + '<br>'
                                          + '</div>'
                                          + '<div style="border-bottom: 1px solid rgba(255,255,255,.3) ;padding-bottom: 7px;margin-bottom: 7px">'
                                          + label[2] + ': ' + value[0] + '<br>'
                                          + label[3] + ': ' + value[1] + '<br>'
                                          + label[4] + ': ' + value[2] + '%<br>'
                                          + '</div>'
                                          + 'Click the point to see all overlapped data.'
                                  }

                              }
                          },
                          visualMap: [
                              {
                                  type: 'continuous', left: 'right', top: 'middle', calculable: true, precision: 0.1,
                                  text: ['% of comment lines'], textGap: 30, dimension: 2, max: 100,
                                  inRange: {symbolSize: [10, 30]}, controller: {inRange: {color: ['#c23531']},},
                                  formatter: function (value) {
                                      return value + "%"; // 范围标签显示内容。
                                  }
                              },
                          ],
                          dataZoom: [
                              {type: 'inside', xAxisIndex: 0, start: 0, end: 100},
                              {type: 'inside', yAxisIndex: 0, start: 0, end: 100},
                          ],
                      },
                  };
                  timelineChart.setOption(option);
              }

              function getMax(dataset) {
                  let xMax = 0;
                  let yMax = 0;
                  let d2Max = 0;
                  for (let key in dataset) {
                      for (let key2 of datasetKeyArray) {
                          for (let cols of dataset[key][key2]) {
                              xMax = Number(cols[0]) > xMax ? Number(cols[0]) : xMax;
                              yMax = Number(cols[1]) > yMax ? Number(cols[1]) : yMax;
                              d2Max = Number(cols[2]) > d2Max ? Number(cols[2]) : d2Max;
                          }
                      }
                  }
                  return [xMax, yMax, d2Max];
              }

              function optionsFormatter(dataset) {
                  let options = [];
                  for (let i = 0; i < timeRecords.length; i++) {
                      options[i] = {
                          series: [{
                              name: 'Interface', type: 'scatter', animation: false,
                              data: dataset[timeRecords[i]]['Interface'],
                              itemStyle: {color: '#69bae5',},
                              emphasis: {
                                  label: {
                                      show: true, color: '#000000', position: 'top', fontWeight: 'normal',
                                      formatter: function (params) {
                                          return params.data[3];
                                      },
                                  },
                              },
                          }, {
                              name: 'Abstract Class', type: 'scatter', animation: false,
                              data: dataset[timeRecords[i]]['Abstract Class'],
                              itemStyle: {color: '#54ba3d',},
                              emphasis: {
                                  label: {
                                      show: true, color: '#000000', position: 'top', fontWeight: 'normal',
                                      formatter: function (params) {
                                          return params.data[3];
                                      },
                                  },
                              },
                          }, {
                              name: 'Class', type: 'scatter', animation: false,
                              data: dataset[timeRecords[i]]['Class'],
                              itemStyle: {color: '#c23531',},
                              emphasis: {
                                  label: {
                                      show: true, color: '#000000', position: 'top', fontWeight: 'normal',
                                      formatter: function (params) {
                                          return params.data[3];
                                      },
                                  },
                              },
                          }, {
                              name: 'Enum', type: 'scatter', animation: false,
                              data: dataset[timeRecords[i]]['Enum'],
                              itemStyle: {color: '#e7ad70',},
                              emphasis: {
                                  label: {
                                      show: true, color: '#000000', position: 'top', fontWeight: 'normal',
                                      formatter: function (params) {
                                          return params.data[3];
                                      },
                                  },
                              },
                          }, {
                              name: 'Annotation', type: 'scatter', animation: false,
                              data: dataset[timeRecords[i]]['Annotation'],
                              itemStyle: {color: '#e770e1',},
                              emphasis: {
                                  label: {
                                      show: true, color: '#000000', position: 'top', fontWeight: 'normal',
                                      formatter: function (params) {
                                          return params.data[3];
                                      },
                                  },
                              },
                          }, {
                              name: 'package/module-info', type: 'scatter', animation: false,
                              data: dataset[timeRecords[i]]['info.java'],
                              itemStyle: {color: '#171717',},
                              emphasis: {
                                  label: {
                                      show: true, color: '#000000', position: 'top', fontWeight: 'normal',
                                      formatter: function (params) {
                                          return params.data[3];
                                      },
                                  },
                              },
                          }]
                      }
                  }
                  return options;
              }

              // 基于准备好的dom，初始化echarts实例
              let timelineChart = echarts.init(document.getElementById('chart'));

              // 用于显示timeline chart的重叠数据
              let chart_data_vm = new Vue({
                  el: '#chart_data_model',
                  data: {
                      title: '',
                      pointValueList: [],
                      pointDescriptionList: [],
                  }
              })
              let currentTimelineIndex = timeRecords.length - 1;
              timelineChart.on('timelinechanged', function (params) {
                  currentTimelineIndex = params.currentIndex
              });
              timelineChart.on('click', 'series.scatter', function (param) {
                  chart_data_vm.title = timeRecords[currentTimelineIndex];

                  let pointValueList = [];
                  pointValueList.push("Source Lines of Code : " + param.value[0]);
                  pointValueList.push("Comment Lines: " + param.value[1]);
                  pointValueList.push("% of Comment Lines: " + param.value[2] + "%");
                  chart_data_vm.pointValueList = pointValueList;

                  let x = param.value[0];
                  let y = param.value[1];
                  let pointDescriptionList = [];
                  for (let key in currentDataset) {
                      if (key === timeRecords[currentTimelineIndex]) {
                          for (let key2 of ['Interface', 'Abstract Class', 'Class', 'Enum', 'Annotation']) {
                              for (let row of currentDataset[key][key2]) {
                                  if (row[0] === x && row[1] === y) {
                                      let text;
                                      if (chartLevel === "file") {
                                          text = '<span style="font: 12px">'
                                              + 'File: ' + row[3] + '.java</span>' + '<br>'
                                              + '<span style="font: 12px">'
                                              + 'Of module: ' + row[4] + '</span>' + '<br>';
                                      } else {
                                          text = '<span style="font: 12px">'
                                              + key2 + ': ' + row[3] + '</span>' + '<br>'
                                              + '<span style="font: 12px">'
                                              + 'Of module: ' + row[4] + '</span>' + '<br>';
                                      }
                                      pointDescriptionList.push(text);
                                  }
                              }
                          }
                      }
                  }
                  chart_data_vm.pointDescriptionList = pointDescriptionList;
                  $('#chart_data_model').modal('show');
              });
					
					
					</script>
				</div>
			</div>
		</div>
		
		<!--表格-->
		<div class="row">
			<!-- 选择记录时间 -->
			<div class="col-xl-12">
				<div class="card-header border-0">
					<div class="row align-items-center">
						<div class="col-auto">
							<h6 class="text-uppercase text-muted ls-1 mb0">Details</h6>
							
							<!-- dropdown -->
							<div class="nav-item dropdown">
								<a class="nav-link pr-0" href="#" role="button" data-toggle="dropdown" aria-haspopup="true"
								   aria-expanded="false">
											<span class="h3 mb-0 mr-2" id="current_record_time"
											      th:text="${#dates.format(currentProjectInfo.getCreateDate(), 'yyyy-MM-dd HH:mm:ss')}"></span>
									<i class="fas fa-caret-down"></i>
								</a>
								<div class="dropdown-menu">
									<a th:class="${timeRecordStat.index} eq ${timeRecords.size()-1} ? 'dropdown-item active' : 'dropdown-item'"
									   href="javascript:void(0);"
									   th:each="timeRecord,timeRecordStat : ${timeRecords}"
									   th:onclick="selectRecordTime(this,[[${timeRecordStat.index}]])">
										<span th:text="${timeRecord}"></span>
									</a>
								</div>
							</div>
						
						</div>
					
					</div>
				</div>
			</div>
			<!--表格-->
			<div class="col-xl-12">
				<div class="card table-outline">
					<div class="table-responsive">
						<div id="toolbar">
							<div class="form-inline" role="form">
								<a id="previous-btn" class="btn btn-outline-primary btn-sm invisible"
								   href="javascript:void(0);"
								   onclick="previousTable()">
									< previous</a>
							</div>
						</div>
						<table id="table"></table>
					</div>
				</div>
			</div>
			<!-- Modal -->
			<div class="modal fade" id="row_model" tabindex="-1" role="dialog"
			     aria-labelledby="row_model_label" aria-hidden="true">
				<div class="modal-dialog modal-dialog-centered modal-xl" role="document">
					<div class="modal-content">
						<div class="modal-header">
							<h5 class="modal-title" id="row_model_label">
								<span class="h3 text-uppercase text-muted mr-2">{{ recordType }}</span>
								<span class="h3">{{ recordName }}</span>
							</h5>
							<button type="button" class="close" data-dismiss="modal" aria-label="Close">
								<span aria-hidden="true">&times;</span>
							</button>
						</div>
						<div class="modal-body">
							<div id="row_chart" class="card-body pb-4 px-4 pl-0 pt-0 col-12" style="height:450px;"></div>
						</div>
						<div class="modal-footer">
							<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
						</div>
					</div>
				</div>
			</div>
		</div>
		<!--common modals-->
		<modal th:replace="fragments/common :: modals"></modal>
		<!-- Footer -->
		<footer th:replace="fragments/common :: footer"></footer>
	</div>
</div>
<script th:replace="fragments/common :: footer_imports"></script>
<script>

    $(function () {
        // 首次渲染图表
        changeDataSet("file");
        // 首次渲染表格
        showModuleSloc();
    })

    let $table = $('#table')
    let projectRecordIndex = -1;
    let currentIndex = 0;
    let requestHistory = new Array();

    // 选择记录
    function selectRecordTime(obj, index) {
        projectRecordIndex = index;
        let newTime = $(obj).text()
        $('#current_record_time').text(newTime)
        $(obj).siblings().removeClass("active")
        $(obj).addClass("active");
        if (currentIndex === 0) {
            showModuleSloc();
        } else {
            showPackageSloc(requestHistory[currentIndex].name, requestHistory[currentIndex].isNameOfModule, false);
        }
    }

    //表格：模块级别的度量数据
    function showModuleSloc() {
        let columns = [{
            field: 'chart', title: ''
        }, {
            field: 'name', title: 'Module Name', sortable: true,
            formatter: function (value, row) {
                if (row.level === "module") {
                    return '<a href="javascript:void(0);" ' +
                        'onclick="showPackageSloc(\'' + row.name.replace(/\\/g, "\\\\") + '\',true,true)">' +
                        value + '</a>';
                } else {
                    return value;
                }
            },
        }, {
            field: 'level', title: 'Level', sortable: true
        }, {
            field: 'physicalCodeLinesSF', title: 'Source Lines of Code<br>(Source File)', sortable: true
        }, {
            field: 'CommentLinesSF', title: 'Number of Comment Lines<br>(Source File)', sortable: true
        }, {
            field: 'percentageOfCommentSF', title: '% of Comment Lines<br>(Source File)', sortable: true
        }, {
            field: 'physicalCodeLinesJP', title: 'Source Lines of Code<br>(JavaParser)', sortable: true
        }, {
            field: 'CommentLinesJP', title: 'Number of Comment Lines<br>(JavaParser)', sortable: true
        }, {
            field: 'percentageOfCommentJP', title: '% of Comment Lines<br>(JavaParser)', sortable: true
        }];
        $.get("/dashboard/sloc/table/module?projectRecordIndex=" + projectRecordIndex).done(function (data) {
            let dataset = data;
            //给每行前面加上趋势图按钮（弹出模态框）
            for (i = 0; i < dataset.length; i++) {
                dataset[i].chart =
                    '<a class="table-chart-icon" href="javascript:void(0);" data-toggle="modal" '
                    + 'data-target="#row_model" onclick="showTableChart(\'' +
                    dataset[i].name.replace(/\\/g, "\\\\") + '\',\'' + dataset[i].level + '\')">'
                    + '<i class="fas fa-chart-bar"></i></a>'
            }
            buildTable($table, dataset, columns, 2, 0)
            $("#previous-btn").addClass("invisible");
        });
    }

    //表格：类级别的度量数据
    function showPackageSloc(name, isNameOfModule, isRequestNext) {
        if (isRequestNext) {
            currentIndex++;
            requestHistory[currentIndex] = {
                name: name,
                isNameOfModule: isNameOfModule,
            };
        }
        let columns = [{
            field: 'chart', title: ''
        }, {
            field: 'name', title: 'Package/Class Name', sortable: true,
            formatter: function (value, row) {
                if (row.level === "package") {
                    return '<a href="javascript:void(0);" ' +
                        'onclick="showPackageSloc(\'' + value + '\',false,true)">' +
                        value + '</a>';
                } else {
                    return value;
                }
            },
        }, {
            field: 'level', title: 'Level', sortable: true
        }, {
            field: 'module', title: 'of Which Module', sortable: true
        }, {
            field: 'physicalCodeLinesSF', title: 'Source Lines of Code<br>(Source File)', sortable: true
        }, {
            field: 'CommentLinesSF', title: 'Number of Comment Lines<br>(Source File)', sortable: true
        }, {
            field: 'percentageOfCommentSF', title: '% of Comment Lines<br>(Source File)', sortable: true
        }, {
            field: 'physicalCodeLinesJP', title: 'Source Lines of Code<br>(JavaParser)', sortable: true
        }, {
            field: 'CommentLinesJP', title: 'Number of Comment Lines<br>(JavaParser)', sortable: true
        }, {
            field: 'percentageOfCommentJP', title: '% of Comment Lines<br>(JavaParser)', sortable: true
        }];
        let requestPath;
        if (isNameOfModule) {
            requestPath =
                "/dashboard/sloc/table/package";
        } else {
            requestPath = "/dashboard/sloc/table/subpackage";
        }
        $.post(requestPath, {
            name: name,
            projectRecordIndex: projectRecordIndex
        }, function (data) {
            let dataset = data;
            //给每行前面加上趋势图按钮（弹出模态框）
            for (i = 0; i < dataset.length; i++) {
                let param1;
                if (dataset[i].level === "class") {
                    param1 = dataset[i].qualifiedName;
                } else {
                    param1 = dataset[i].name;
                }
                dataset[i].chart =
                    '<a class="table-chart-icon" href="javascript:void(0);" data-toggle="modal" '
                    + 'data-target="#row_model" onclick="showTableChart(\'' +
                    param1.replace(/\\/g, "\\\\") + '\',\'' + dataset[i].level + '\')">'
                    + '<i class="fas fa-chart-bar"></i></a>'
            }
            buildTable($table, dataset, columns, 2, 0)
            $("#previous-btn").removeClass("invisible");
        })
    }

    // 重新渲染表格
    function buildTable($el, dataset, columns, fixedNumber, fixedRightNumber) {
        $el.bootstrapTable('destroy').bootstrapTable({
            height: 500,
            columns: columns,
            data: dataset,
            toolbar: '#toolbar',
            search: true,
            showColumns: true,
            fixedColumns: true,
            fixedNumber: fixedNumber,
            fixedRightNumber: fixedRightNumber,
            // buttons: "",
            // buttonsPrefix: "",
            // buttonsClass: "btn btn-sm btn-outline-primary",
            showColumnsToggleAll: true,
            detailViewByClick: true,
            iconSize: "sm",
            showFullscreen: true,
        })
    }

    // 表格：返回上一级
    function previousTable() {
        currentIndex--;
        if (currentIndex === 0) {
            showModuleSloc();
        } else {
            showPackageSloc(requestHistory[currentIndex].name, requestHistory[currentIndex].isNameOfModule, false);
        }
    }

    // 指定图表的配置项和数据
    let option2 = {
        legend: {},
        grid: {
            bottom: '100'
        },
        // 声明一个 X 轴，类目轴（category）。默认情况下，类目轴对应到 dataset 第一列。
        xAxis: {
            type: 'category'
        },
        yAxis: [
            {
                name: "Number of Lines (SLOC/NOCL)",
                type: 'value',
                nameLocation: 'center',
                nameRotate: 90,
                nameGap: 40
            }, {
                name: "% of Comment Lines",
                type: 'value',
                nameLocation: 'center',
                nameRotate: 270,
                nameGap: 35,
            }
        ],
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                snap: true,
                type: "line",
            }
        },
        dataZoom: [
            {
                type: 'slider',
                xAxisIndex: 0,
                start: 0,
                end: 100
            },
            {
                type: 'inside',
                xAxisIndex: 0,
                start: 0,
                end: 100
            },
            {
                type: 'slider',
                yAxisIndex: 0,
                left: 0,
                start: 0,
                end: 100
            },
            {
                type: 'slider',
                yAxisIndex: 1,
                right: 0,
                start: 0,
                end: 100
            }
        ],
    };
    let timelineChart2 = echarts.init(document.getElementById('row_chart'));
    timelineChart2.setOption(option2);

    // 用于修改模块框title
    let vm_sloc_chart_title = new Vue({
        el: '#row_model_label',
        data: {
            recordType: '',
            recordName: '',
        }
    })

    function showTableChart(name, level) {
        vm_sloc_chart_title.recordName = name;
        vm_sloc_chart_title.recordType = level;
        // 异步加载数据
        timelineChart2.clear();
        timelineChart2.setOption(option2);
        // 异步加载数据
        $.post("/dashboard/sloc/table/chart", {
            name: name,
            level: level
        }, function (data) {
            // 填入数据
            console.log(data)
            timelineChart2.setOption({
                dataset: {
                    source: data
                },
                series: [
                    {
                        type: 'line', name: 'Source Lines of Code (Source File)', yAxisIndex: 0,
                        lineStyle: {width: 3}, emphasis: {label: {show: true}},
                    },
                    {
                        type: 'line', name: 'Number of Comment Lines (Source File)', yAxisIndex: 0,
                        lineStyle: {width: 3}, emphasis: {label: {show: true}},
                    },
                    {
                        type: 'line', name: '% of Comment Lines (Source File)', yAxisIndex: 1,
                        lineStyle: {width: 3, type: "dashed"}, emphasis: {label: {show: true}},
                    },
                    {
                        type: 'line', name: 'Source Lines of Code (JavaParser)', yAxisIndex: 0,
                        lineStyle: {width: 3}, emphasis: {label: {show: true}},
                    },
                    {
                        type: 'line', name: 'Number of Comment Lines (JavaParser)', yAxisIndex: 0,
                        lineStyle: {width: 3}, emphasis: {label: {show: true}},
                    },
                    {
                        type: 'line', name: '% of Comment Lines (JavaParser)', yAxisIndex: 1,
                        lineStyle: {width: 3, type: "dashed"}, emphasis: {label: {show: true}},
                    },
                ],
            });
        })
    }

    // 让echarts在模态框打开后重新渲染
    $('#row_model').on('shown.bs.modal', function () {
        timelineChart2.resize()
    })

</script>

</body>

</html>
